package bll

import (
	"context"
	"fmt"
	"gitlab.local/backend/proto/dto"
	"gitlab.local/backend/proto/manager"
	"pay/client/grpc"
	log "pay/collector/logger"

	"pay/model"
	"pay/model/entity"
	"pay/model/mapping"
	"pay/store"
	"pay/store/postgres"
	"time"
)

type feePlanPaymentOrder struct {
	iFeePlanPaymentOrder store.IFeePlanPaymentOrder
	iFeePlan             store.IFeePlan
}

var FeePlanPaymentOrder = &feePlanPaymentOrder{
	iFeePlanPaymentOrder: postgres.FeePlanPaymentOrder,
	iFeePlan:             postgres.FeePlan,
}

func init() {
	Register(FeePlanPaymentOrder)
}

func (a *feePlanPaymentOrder) init() func() {
	return func() {}
}

// Create
func (a *feePlanPaymentOrder) Create(ctx context.Context, in *model.FeePlanPaymentOrderCreateRequest) (int64, error) {
	c := buildFeePlanPaymentOrder(in)

	return a.iFeePlanPaymentOrder.Create(ctx, c)
}

// Update
func (a *feePlanPaymentOrder) Update(ctx context.Context, in *model.FeePlanPaymentOrderUpdateRequest) error {
	var (
		dict = make(map[string]interface{})
	)

	if in.Id != nil {
		dict["id"] = in.Id
	}

	if in.TradeNo != nil {
		dict["trade_no"] = in.TradeNo
	}

	if in.PrepayId != nil {
		dict["prepay_id"] = in.PrepayId
	}

	if in.UserId != nil {
		dict["user_id"] = in.UserId
	}

	if in.UserName != nil {
		dict["user_name"] = in.UserName
	}

	if in.UserPhone != nil {
		dict["user_phone"] = in.UserPhone
	}

	if in.EbikeId != nil {
		dict["ebike_id"] = in.EbikeId
	}

	if in.EbikeName != nil {
		dict["ebike_name"] = in.EbikeName
	}

	if in.EbikeSnCode != nil {
		dict["ebike_sn_code"] = in.EbikeSnCode
	}

	if in.EbikeTypeId != nil {
		dict["ebike_type_id"] = in.EbikeTypeId
	}

	if in.EbikeTypeName != nil {
		dict["ebike_type_name"] = in.EbikeTypeName
	}

	if in.Status != nil {
		dict["status"] = in.Status
	}

	if in.StatusDetail != nil {
		dict["status_detail"] = in.StatusDetail
	}

	if in.Description != nil {
		dict["description"] = in.Description
	}

	if in.FeePlanId != nil {
		dict["fee_plan_id"] = in.FeePlanId
	}

	if in.FeePlanGroupId != nil {
		dict["fee_plan_group_id"] = in.FeePlanGroupId
	}

	if in.FeePlanPackNo != nil {
		dict["fee_plan_pack_no"] = in.FeePlanPackNo
	}

	if in.Money != nil {
		dict["money"] = in.Money
	}

	if in.CallBackCnt != nil {
		dict["call_back_cnt"] = in.CallBackCnt
	}

	if in.Channel != nil {
		dict["channel"] = in.Channel
	}

	if in.CallBackData != nil {
		dict["call_back_data"] = in.CallBackData
	}

	if in.TransactionId != nil {
		dict["transaction_id"] = in.TransactionId
	}

	if in.ExpiredAt != nil {
		dict["expired_at"] = in.ExpiredAt
	}

	if in.PayAt != nil {
		dict["pay_at"] = in.PayAt
	}

	if in.CreatedAt != nil {
		dict["created_at"] = in.CreatedAt
	}

	if in.UpdatedAt != nil {
		dict["updated_at"] = in.UpdatedAt
	}

	// do other update here
	updateAt := time.Now().Unix()
	in.UpdatedAt = &updateAt
	return a.iFeePlanPaymentOrder.Update(ctx, *in.Id, dict)
}

// Delete
func (a *feePlanPaymentOrder) Delete(ctx context.Context, in *model.FeePlanPaymentOrderDeleteRequest) error {
	return a.iFeePlanPaymentOrder.Delete(ctx, in.Id)
}

// List
func (a *feePlanPaymentOrder) List(ctx context.Context, in *model.FeePlanPaymentOrderListRequest) (*model.FeePlanPaymentOrderListResponse, error) {
	var (
		err            error
		total          int
		planIds        []int64
		planIdNo2Index = map[string]int{}
		list           []*entity.FeePlanPaymentOrder
		out            = &model.FeePlanPaymentOrderListResponse{}
		opt            = model.QueryOptions{OrderFields: model.NewOrderFields(model.NewOrderField("id", model.OrderByDESC))}
	)

	if total, list, err = a.iFeePlanPaymentOrder.List(ctx, in, opt); err != nil {
		return nil, err
	}

	out.Total = total
	out.List = mapping.FeePlanPaymentOrdersEntityToDto(list)

	for i, v := range list {
		planIdNo2Index[fmt.Sprintf("%v_%v", v.Id, v.FeePlanPackNo)] = i
		planIds = append(planIds, v.FeePlanId)
	}

	return out, nil
}

// Find
func (a *feePlanPaymentOrder) Find(ctx context.Context, in *model.FeePlanPaymentOrderInfoRequest) (*model.FeePlanPaymentOrderInfo, error) {
	var (
		err  error
		data *entity.FeePlanPaymentOrder
		out  = &model.FeePlanPaymentOrderInfo{}
	)

	if data, err = a.iFeePlanPaymentOrder.Find(ctx, in); err != nil {
		return nil, err
	}

	out = mapping.FeePlanPaymentOrderEntityToDto(data)
	return out, nil
}

// buildFeePlanPaymentOrder build entity
func buildFeePlanPaymentOrder(in *model.FeePlanPaymentOrderCreateRequest) *entity.FeePlanPaymentOrder {

	ety := &entity.FeePlanPaymentOrder{}

	ety.Id = in.Id

	ety.TradeNo = in.TradeNo

	ety.PrepayId = in.PrepayId

	ety.UserId = in.UserId

	ety.UserName = in.UserName

	ety.UserPhone = in.UserPhone

	ety.EbikeId = in.EbikeId

	ety.EbikeName = in.EbikeName

	ety.EbikeSnCode = in.EbikeSnCode

	ety.EbikeTypeId = in.EbikeTypeId

	ety.EbikeTypeName = in.EbikeTypeName

	ety.Status = in.Status

	ety.Description = in.Description

	ety.FeePlanId = in.FeePlanId

	ety.FeePlanGroupId = in.FeePlanGroupId

	ety.FeePlanPackNo = in.FeePlanPackNo

	ety.Money = in.Money

	ety.CallBackCnt = in.CallBackCnt

	ety.Channel = in.Channel

	ety.CallBackData = in.CallBackData

	ety.TransactionId = in.TransactionId

	ety.CreatedAt = time.Now().Unix()

	ety.UpdatedAt = in.UpdatedAt

	var (
		ctx, _ = context.WithTimeout(context.Background(), time.Minute*5)
	)
	resp, err := grpc.EbkieService.GetEbikeInfo(ctx, &manager.EbikeInfoReq{
		BikeId: &in.EbikeId,
	})
	if err != nil {
		log.Error(fmt.Sprintf("获取车辆[%v]信息失败:%+v", in.EbikeId, err))
	} else {
		ety.EbikeName = resp.BikeInfo.Name
		ety.EbikeSnCode = resp.BikeInfo.SnCode
		ety.EbikeTypeId = resp.BikeInfo.BikeTypeId
		ety.EbikeTypeName = resp.BikeInfo.BikeTypeName
		ety.UserId = resp.BikeInfo.UserId
	}

	if ety.UserId > 0 {
		respUser, err := grpc.UserService.UserInfo(ctx, &dto.UserInfoRequest{Id: ety.UserId})
		if err != nil {
			log.Error(fmt.Sprintf("获取车辆用户[%v]信息失败:%+v", in.EbikeId, err))
		} else {
			ety.UserName = respUser.Name
			ety.UserPhone = respUser.Phone
		}
	}
	return ety
}
